function [FinalCurve]=RibCageApproximation(I,Thres);
%Draw a closed curve which approximates the cross
%section of the rib cage in CT slices.
% [FinalCurve]=RibCageApproximation(I,Thres);
% Input parameters
% Img=> the CT slice
% Thres=> the desired threshold for the ribs (bones) extraction.
Img=squeeze(I);
%apply threshold
BinaryImage=Img>Thres;
%perform morphological open operation
BinaryImage = imopen(BinaryImage,strel([1 1;1 1]));
%find the pixels of the rib cage.
[x,y]=find(BinaryImage==1);
%define the center of the image.
ImgCenter =round( [size(BinaryImage)]./2);
%Estimate the vector between bone pixels and image centre
vector = [x-ImgCenter(1),y-ImgCenter(2)];
%Vector's angle in degrees.
Angle = mod(360+180/pi*atan2(vector(:,2),vector(:,1)),360);
%In each directions (0, 10,...., 360 degrees), define the bone pixel which is closer to the image
%center and keep it for the interpolation process.
Theta=[0:10:360];k=0;
Ind=cell([length(Theta)-1,1]);
for i =1:length(Theta)-1
[Ind{i,1}] = find(Angle>=Theta(i) & Angle<Theta(i+1));
if ~isempty(Ind{i,1})
IndMinDist = FunctionMinDistance(x(Ind{i,1}),y(Ind{i,1}),ImgCenter(1),ImgCenter(2));
k=k+1;
IndOfMinDistance(k,1)=Ind{i,1}(IndMinDist(1),1);
end
end
%Set points with the minimum distance from the center of the ribs cavity in an order
[xi, yi]=PixelsInOrder(x(IndOfMinDistance),y(IndOfMinDistance),ImgCenter(1),ImgCenter(2));
%Cubic interpolation
[xii, yii] = Curvefitting(xi,yi,0.2);
xii = round(xii);yii=round(yii);
%Draw the final curve
FinalCurve=zeros(size(BinaryImage));
for i =1:length(xii)
FinalCurve(xii(i),yii(i))=1;
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
function IndOfMinDistance = FunctionMinDistance(I,J,c1,c2)
%This function calculates the distance between each contour (I,J) point and
%the centre of the contour
%and finds the edge with the minimum distance
% IndOfMinDistance = FunctionMinDistance(I,J,c1,c2)
% Input Parameters
% [I,J] points coordinates
% [c1,c2] coordinates of the centre of the contour
MinDistance = zeros(length(I),1);
MinDistance(:) = sqrt((I(:)-c1).^2+(J(:)-c2).^2);
IndOfMinDistance =find (MinDistance <= min (MinDistance));
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [Final_x, Final_y]=PixelsInOrder(x,y,c1,c2);
%Define a cartesian system xy with center[c1,c2],
%Set the points [x,y] in a circular order according to theirs angles
% [Final_x, Final_y]=PixelsInOrder(x,y,c1,c2);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
c1=round(c1);c2=round(c2);
vector = [x-c1,y-c2];
%estimate the angle between the cartesian axis x and the points [x,y]
Theta = mod(360+180/pi*atan2(vector(:,2),vector(:,1)),360);
%sort the [x,y] points
[ThetaSorted,Ind] = sort(Theta);
Final_x=zeros(length(x),1);
Final_y=zeros(length(y),1);
Final_x(1:length(x)) =x(Ind);
Final_y(1:length(y)) =y(Ind);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [xi,yi] = Curvefitting(x,y,RES)
% Interpolate(cubic) the points of the image in order to create a close curve
% [xi,yi] =Curvefitting(x,y,RES)
%
% RES: resolution desired
%
% Modified Code by A. Koulouri
%
% Chenyang Xu and Jerry L. Prince, 3/8/96, 6/17/97
% Copyright (c) 1996-97 by Chenyang Xu and Jerry L. Prince
% Image Analysis and Communications Lab, Johns Hopkins University
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% convert to column vector
x = x(:); y = y(:);
N = length(x);
% make it a circular list since we are dealing with closed contour
x = [x;x(1)];
y = [y;y(1)];
dx = x([2:N+1])- x(1:N);
dy = y([2:N+1])- y(1:N);
d = sqrt(dx.*dx+dy.*dy); % compute the distance from previous node for point 2:N+1
d = [0;d]; % point 1 to point 1 is 0
% now compute the arc length of all the points from the first point [x(1),
% y(1)].
% we use matrix multiply to achieve summing
M = length(d);
d = (d'*uppertri(M,M))';
% now ready to reparametrize the closed curve in terms of arc length
maxd = d(M);
if (maxd/RES<3)
error('RES too big compare to the length of original curve');
end
di = 0:RES:maxd;
xi = interp1(d,x,di,'cubic');
yi = interp1(d,y,di,'cubic');
N = length(xi);
if (maxd - di(length(di)) <RES/2) % deal with end boundary condition
xi = xi(1:N-1);
yi = yi(1:N-1);
end
function X = uppertri(M,N)
% UPPERTRI Upper triagonal matrix
% UPPER(M,N) is a M-by-N triagonal matrix
[J,I] = meshgrid(1:M,1:N);
X = (J>=I);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%